package com.hzy.nursing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzy.common.constant.CacheConstants;
import com.hzy.common.core.domain.AjaxResult;
import com.hzy.common.exception.base.BaseException;
import com.hzy.common.utils.StringUtils;
import com.hzy.framework.config.properties.AliIoTConfigProperties;
import com.hzy.nursing.domain.Device;
import com.hzy.nursing.dto.DeviceDto;
import com.hzy.nursing.mapper.DeviceMapper;
import com.hzy.nursing.service.IDeviceService;
import com.hzy.nursing.vo.DeviceVo;
import com.hzy.nursing.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 设备Service业务层处理
 *
 * @author HZY
 * @date 2025-10-12
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {
    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private Client client;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Override
    public AjaxResult queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 查询物模型数据，调用失败");
        }
        if (!response.getBody().success) {
            throw new BaseException(response.getBody().getErrorMessage());
        }
        return AjaxResult.success(response.getBody().getData());
    }

    @Override
    public AjaxResult queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse;
        try {
            //查询设备属性状态
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 查询设备属性状态，调用失败");
        }
        if (!queryDevicePropertyStatusResponse.getBody().success) {
            throw new BaseException(queryDevicePropertyStatusResponse.getBody().getErrorMessage());
        }
        //封装数据返回
        return AjaxResult.success(queryDevicePropertyStatusResponse.getBody().getData());
    }

    @Override
    public DeviceVo queryDeviceDetail(DeviceDto deviceDto) {
        //查询iot平台中的设备数据
        QueryDeviceDetailRequest queryDeviceDetailRequest = new QueryDeviceDetailRequest();
        queryDeviceDetailRequest.setIotId(deviceDto.getIotId());
        queryDeviceDetailRequest.setProductKey(deviceDto.getProductKey());
        queryDeviceDetailRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(queryDeviceDetailRequest);
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 查询设备，调用失败");
        }
        //安全校验
        if (!response.getBody().success) {
            throw new RuntimeException("物联网接口 - 查询设备，调用失败");
        }

        //查询表中的数据
        Device device = getOne(Wrappers.<Device>lambdaQuery().eq(Device::getIotId, deviceDto.getIotId()));

        DeviceVo deviceVo = BeanUtil.toBean(device, DeviceVo.class);

        //合并
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        BeanUtil.copyProperties(data, deviceVo, CopyOptions.create().ignoreNullValue());
        return deviceVo;
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //判断设备名称是否重复
        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getDeviceName, deviceDto.getDeviceName());
        long count = count(queryWrapper);
        if (count > 0) {
            throw new BaseException("设备名称已存在，请重新输入");
        }
        //保存设备到iot平台
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response;
        try {
            response = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 注册设备，调用失败");
        }

        //判断接口是否调通
        if (!response.getBody().success) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        //查询产品数据
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse queryProductResponse;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 查询产品，调用失败");
        }
        //判断接口是否调通
        if (!queryProductResponse.getBody().success) {
            throw new BaseException("物联网接口 - 查询产品，调用失败");
        }

        //保存到数据库
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setProductName(queryProductResponse.getBody().getData().productName);

        //物理位置
        if (device.getLocationType().equals(0)) {
            device.setPhysicalLocationType(-1);
        }

        //补全设备id
        device.setIotId(response.getBody().getData().getIotId());

        device.setCreateTime(new Date());

        try {
            deviceMapper.insertDevice(device);
        } catch (Exception e) {

            //删除iot中的设备
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setDeviceName(device.getDeviceName());
            deleteDeviceRequest.setProductKey(device.getProductKey());
            deleteDeviceRequest.setIotId(device.getIotId());
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            try {
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new BaseException("物联网接口 - 删除设备，调用失败");
            }
            throw new BaseException("该老人/位置已绑定该产品，请重新选择");
        }
    }

    @Override
    public List<ProductVo> allProduct() {
        //从redis中查询数据
        String jsonStr = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
        //如果数据为空，则返回一个空集合
        if (StringUtils.isEmpty(jsonStr)) {
            return Collections.emptyList();
        }
        //解析数据，并返回
        return JSONUtil.toList(jsonStr, ProductVo.class);
    }

    @Override
    public void syncProductList() {
        //请求参数
        QueryProductListRequest request = new QueryProductListRequest();
        request.setPageSize(200);
        request.setCurrentPage(1);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        //调用第三方查询产品列表
        QueryProductListResponse response;
        try {
            response = client.queryProductList(request);
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 查询产品，同步失败");
        }

        //判断，如果数据为空，则中断请求
        if (!response.getBody().success) {
            throw new BaseException("物联网接口 - 查询产品，调用失败");
        }

        //存储到redis
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(response.getBody().getData().getList().getProductInfo()));
    }

    @Override
    public Device selectDeviceById(Long id) {
        return getById(id);
    }

    @Override
    public List<Device> selectDeviceList(Device device) {
        return deviceMapper.selectDeviceList(device);
    }

    @Override
    public int insertDevice(Device device) {
        return save(device) ? 1 : 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDevice(Device device) {
        //查询设备是否存在
        Device dbDevice = getById(device.getId());
        if (ObjectUtil.isEmpty(dbDevice)) {
            throw new BaseException("设备不存在");
        }
        //先更新设备
        //如果是随身设备，物理位置设为-1
        if (device.getLocationType().equals(0)) {
            device.setPhysicalLocationType(-1);
        }
        //更新数据库中设备信息
        try {
            deviceMapper.updateDevice(device);
        } catch (Exception e) {
            throw new BaseException("该老人/位置已绑定该产品，请重新选择");
        }

        //批量更新设备昵称
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //更新设备昵称（批量）
        //集合主要作用是装入多个设备
        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> list = new ArrayList<>();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo info = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        //属性拷贝
        BeanUtil.copyProperties(device, info);
        list.add(info);
        request.setDeviceNicknameInfo(list);
        BatchUpdateDeviceNicknameResponse response;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException("IOT调用，更新设备失败");
        }
        //判断接口接通了
        if (!response.getBody().success) {
            throw new BaseException(response.getBody().getErrorMessage());
        }
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDeviceByIds(Long[] ids) {
        List<Long> idList = Arrays.asList(ids);
        if (idList.isEmpty()) {
            return 0;
        }

        // 1. 为了获取调用IoT接口所需的iotId等信息，先根据ids批量查询出完整的设备信息
        List<Device> devicesToDelete = deviceMapper.selectBatchIds(idList);
        if (devicesToDelete.isEmpty()) {
            // 如果根据id没有查到任何设备，直接返回
            return 0;
        }

        // 2. 循环遍历，逐个删除IoT云端的设备
        for (Device device : devicesToDelete) {
            DeleteDeviceRequest deleteRequest = new DeleteDeviceRequest();
            deleteRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteRequest.setProductKey(device.getProductKey());
            deleteRequest.setDeviceName(device.getDeviceName());
            deleteRequest.setIotId(device.getIotId());

            try {
                DeleteDeviceResponse response = client.deleteDevice(deleteRequest);
                // 如果云端删除失败，则抛出异常，整个事务回滚
                if (!response.getBody().getSuccess()) {
                    throw new BaseException("物联网接口 - 删除设备 " + device.getDeviceName() + " 失败: " + response.getBody().getErrorMessage());
                }
            } catch (Exception e) {
                throw new BaseException("物联网接口 - 调用删除设备接口时发生异常");
            }
        }

        // 3. 所有云端设备都成功删除后，再批量删除数据库中的记录
        int deletedCount = deviceMapper.deleteBatchIds(idList);

        return deletedCount;
    }


    // =================================================================
    // =========== 【修改点】: 替换掉下面这个错误的方法 =======================
    // =================================================================

    /**
     * 删除设备信息 (修改后版本)
     * @param id 设备主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDeviceById(Long id)
    {
        // 1. 为了获取调用IoT接口所需的信息，先根据id查询出完整的设备信息
        Device deviceToDelete = deviceMapper.selectById(id);

        // 如果设备不存在，则无需继续操作
        if (deviceToDelete == null) {
            return 0;
        }

        // 2. 创建请求，准备删除IoT云端的设备
        DeleteDeviceRequest deleteRequest = new DeleteDeviceRequest();
        deleteRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        deleteRequest.setProductKey(deviceToDelete.getProductKey());
        deleteRequest.setDeviceName(deviceToDelete.getDeviceName());
        deleteRequest.setIotId(deviceToDelete.getIotId());

        try {
            DeleteDeviceResponse response = client.deleteDevice(deleteRequest);
            // 如果云端删除失败，则抛出异常，整个事务回滚
            if (!response.getBody().getSuccess()) {
                throw new BaseException("物联网接口 - 删除设备 " + deviceToDelete.getDeviceName() + " 失败: " + response.getBody().getErrorMessage());
            }
        } catch (Exception e) {
            throw new BaseException("物联网接口 - 调用删除设备接口时发生异常");
        }

        // 3. 云端设备成功删除后，再删除数据库中的记录
        int deletedCount = deviceMapper.deleteById(id);

        return deletedCount;
    }
}